package xyz.guhong.play.core;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import xyz.guhong.play.entity.Area;
import xyz.guhong.play.entity.City;
import xyz.guhong.play.entity.Province;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.*;

/**
 * 行政区划信息核心类
 *
 * 只需要调用
 * DataLocationCore.start()
 * 即可使用
 *
 * @author 李双凯
 */
public class DataLocationCore {


    private static Logger logger = LoggerFactory.getLogger(DataLocationCore.class);

    /**
     * json文件来源于一个git项目
     * 该项目是爬取了“国家统计局”的数据
     * git上详细的json文件
     * https://github.com/mumuy/data_location
     */
    private final static String PATH = "D:\\作业\\JavaPlay\\data_location\\src\\main\\resources\\json\\list.json";

    /**
     * 省集合
     */
    private static Set<Province> provinceSet = new HashSet<Province>();

    /**
     * 市集合
     */
    private static Set<City> citySet = new HashSet<City>();

    /**
     * 县集合
     */
    private static Set<Area> areaSet = new HashSet<Area>();


    /**
     * 启动方法
     * @return
     */
    public static JSONObject start(){
        try{
            String text = readJson();
            JSONObject jsonObject = JSON.parseObject(text);
            init(jsonObject);
            return jsonObject;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 读取json
     * @return
     * @throws Exception
     */
    public static String readJson() throws Exception{
        BufferedReader bufferedReader = new BufferedReader(new FileReader(PATH));
        StringBuilder sb = new StringBuilder();
        String temp = null;
        while((temp = bufferedReader.readLine()) != null){
            sb.append(temp);
        }
        return sb.toString();
    }

    /**
     * 初始化：省-市-县
     *
     *  科普一下：
     *  行政区划代码的
     *  第一、二位表示省
     *  第三、四位表示市
     *  第五、六位表示县
     *  https://zhidao.baidu.com/question/190384991.html
     *
     *  拆分行政代码。拆分后，然后通过自交（自己跟自己对比），求交集，得出省市县
     *  没有拆分县城，因为只要得出省和市，那么其他的就是县城了
     *
     *
     * @param jsonObject json对象
     * @return
     */
    public static void init(JSONObject jsonObject){
        for (String key1 : jsonObject.keySet()){

            String provinceKey1 = key1.substring(0,2);
            String cityKey1 = key1.substring(2,4);


            for (String key2 : jsonObject.keySet()){

                String provinceKey2 = key2.substring(0,2);
                String cityKey2 = key2.substring(2,4);


                if(provinceKey1.equals(provinceKey2)){
                    String provinceCode = provinceKey1+"00"+"00";
                    Province province = new Province();
                    province.setCode(provinceCode);
                    province.setName(jsonObject.get(provinceCode).toString());
                    provinceSet.add(province);

                    // !key1.equals(provinceCode) 过滤掉省
                    if((provinceKey1+cityKey1).equals(provinceKey2+cityKey2) && !key1.equals(provinceCode)){
                        String cityCode = provinceKey1+cityKey1+"00";
                        City city = new City();
                        city.setCode(cityCode);
                        try{
                            city.setName(jsonObject.get(cityCode).toString());
                        }catch (NullPointerException e){
                            // 如果没有找到就说明是直辖区。直辖区就是一个省直接管辖的区域。
                            // 参考网站
                            // http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2018/
                            city.setName("直辖区");
                        }
                        city.setProvinceCode(provinceCode);
                        citySet.add(city);

                        // 过滤掉省和市就是县了
                        if(!key1.equals(provinceCode) && !key1.equals(cityCode)){
                            Area area = new Area();
                            area.setCityCode(cityCode);
                            area.setCode(key1);
                            area.setName(jsonObject.get(key1).toString());
                            areaSet.add(area);
                        }
                    }

                }

            }
        }
        logger.debug("初始化成功");
        logger.debug("省份数量："+provinceSet.size());
        logger.debug("市区数量："+citySet.size());
        logger.debug("区县数量："+areaSet.size());
    }

    /**
     * 通过指定code获得旗下的城区
     * @param code
     */
    public  static  void queryList(String code,JSONObject jsonObject){
        if(null == provinceSet || null == citySet || null == areaSet){
            throw new RuntimeException("省市县未初始化！");
        }
        int count = 0;
        // 判断该code属于哪个级别
        if(isExist(code,1)){
            for (City city : citySet) {
                if(city.getProvinceCode().equals(code)){
                    ++count;
                    System.out.println(city.getCode()+":"+city.getName()+":"+city.getProvinceCode());
                }
            }
            System.out.println(get(jsonObject,code)+"下共有"+count+"个市区");
        }else if(isExist(code,2)){
            for (Area area : areaSet) {
                if(area.getCityCode().equals(code)){
                    ++count;
                    System.out.println(area.getCode()+":"+area.getName()+":"+area.getCityCode());
                }
            }
            System.out.println(get(jsonObject,code)+"下共有"+count+"个县城");
        }else if(isExist(code,3)){
            System.out.println(get(jsonObject,code)+"是一个县城，没有下一级了。");
        }else{
            System.out.println("没有查找到【"+code+"】对应的信息");
        }

    }


    public static void showAll(JSONObject jsonObject){
        showProvince();
        showCity(jsonObject);
        showArea(jsonObject);
        System.out.println("省份数量："+provinceSet.size());
        System.out.println("市区数量："+citySet.size());
        System.out.println("区县数量："+areaSet.size());
    }

    public static void showProvince(){
        System.out.println("----------------------------省份列表");
        System.out.println("省份代码:省份名");
        for (Province province : provinceSet) {
            System.out.println(province.getCode()+":"+province.getName());
        }
        System.out.println("省份数量："+provinceSet.size());
    }

    public static void showCity(JSONObject jsonObject){
        System.out.println("----------------------------市区列表");
        System.out.println("市区代码:市区名:省份代码");
        for (City city : citySet) {
            System.out.println(city.getCode()+":"+city.getName()+":"+city.getProvinceCode()+":"+get(jsonObject,city.getProvinceCode()));
        }
        System.out.println("市区数量："+citySet.size());
    }

    public static void showArea(JSONObject jsonObject){
        System.out.println("----------------------------区县列表");
        System.out.println("区县代码:区县名:市区代码");
        for (Area area : areaSet) {
            System.out.println(area.getCode()+":"+area.getName()+":"+area.getCityCode()+":"+get(jsonObject,area.getCityCode()));
        }
        System.out.println("区县数量："+areaSet.size());
    }


    /**
     * 是否存在集合中
     * @param code
     * @param status
     * @return
     */
    private static boolean isExist(String code, Integer status){
        if(status == 1){
            for (Province province : provinceSet) {
                if (province.getCode().equals(code)){
                    return true;
                }
            }
        }else if(status == 2){
            for (City city : citySet) {
                if (city.getCode().equals(code)){
                    return true;
                }
            }
        }else if(status == 3){
            for (Area area : areaSet) {
                if (area.getCode().equals(code)){
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 替代JsonObject.get()方法
     * @return
     */
    private static Object get(JSONObject jsonObject,String code){
        Object obj = jsonObject.get(code);
        if ( null == obj ) {
            return "直辖区";
        }
        return obj;
    }


    public static Set<Province> getProvinceSet() {
        return provinceSet;
    }

    public static Set<City> getCitySet() {
        return citySet;
    }

    public static Set<Area> getAreaSet() {
        return areaSet;
    }
}
